#pragma once

#include "Settings.h"

using namespace System;

namespace Cephei { namespace QL {

	public ref class CSession : public ISession
	{
	private:
		DateTime _evaluationDate;
		int _sessionId;

	internal:
		static int _sessionSequence = 0;
		static System::Threading::ThreadLocal<int>^ _currentSessionId = gcnew System::Threading::ThreadLocal<int> ();

		static property long CurrentSession
		{
			static long get ()
			{
				return _currentSessionId->Value;
			}
		}

	public: 
		generic <typename T>
		virtual T With (T t)
		{
			if (_currentSessionId->Value != _sessionId)
			{
				_currentSessionId->Value = _sessionId;
				Settings::EvaluationDate = _evaluationDate;
			}
			return t;
		}

	internal:
		CSession (DateTime evaluationDate)
		{
			int% i = _sessionSequence;
			_evaluationDate = evaluationDate;
			_sessionId = System::Threading::Interlocked::Increment (i);
			_currentSessionId->Value = _sessionId;
			Settings::EvaluationDate = _evaluationDate;
		}
		~CSession ()
		{
			if (_currentSessionId->Value == _sessionId)
				_currentSessionId->Value = 0;
		}
	};
	
	[FactoryFor(Cephei::QL::ISession_Factory::typeid)]
	public ref class CSession_Factory : public ISession_Factory
	{
	public:
		virtual ISession^ Create (DateTime effectiveDate)
		{
			return REFNEW CSession (effectiveDate);
		}
	};
}}